package com.epi.two;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.regex.*;
import java.util.stream.*;

/**
 * @author dxy
 * @version 1.0
 */
public class IODemo {

    public static void main(String[] args) throws IOException {
//        closeMethod();
//        charsetDemo();
//        outputStreamDemo();
//        objectSerialize();
//        objectDeserialize();
//        pathDemo();
//        fileReadDemo();
//        walkDemo();
//        walkTreeDemo();
//        fileSystemDemo();
//        fileChannelDemo();
//        patternFind();
        patternExact();

    }

    private static void patternExact() {
        boolean isValid = Pattern.matches("\\d{4}", "2025"); // true
        Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);

        String input = "Name: Alice, Age: 25";
        Pattern pattern = Pattern.compile("Name: (\\w+), Age: (\\d+)");
        Matcher matcher = pattern.matcher(input);

        if (matcher.find()) {
            System.out.println("Name: " + matcher.group(1)); // Alice
            System.out.println("Age: " + matcher.group(2));  // 25
        }
    }

    private static void patternFind() {
        String text = "Java 17 is cool!";
        Pattern pattern = Pattern.compile("\\d"); // 匹配数字
        Matcher matcher = pattern.matcher(text);

        while (matcher.find()) {
            System.out.println("找到数字: " + matcher.group()); // 输出 17
        }
    }

    private static void fileChannelDemo() throws IOException {
        Path path = Paths.get("src/main/resources/txt/output.txt");
        try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)) {
//            FileLock lock = channel.lock();
            FileLock lock = channel.tryLock();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (channel.read(buffer) != -1) {
                buffer.flip();
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }
                buffer.clear();
            }
        }
    }

    private static void fileSystemDemo() throws IOException {
        // 默认文件系统
        FileSystem defaultFs = FileSystems.getDefault();
        Path path = defaultFs.getPath("src", "main", "resources");

        //  ZIP 文件系统
        Path zipPath = Paths.get("src/main/resources/test.zip");
        try (FileSystem zipFs = FileSystems.newFileSystem(zipPath, (ClassLoader) null)) {
            for (Path root : zipFs.getRootDirectories()) {
                Files.walk(root)
                    .filter(Files::isRegularFile)
                    .forEach(System.out::println);
            }
        }
    }

    private static void walkTreeDemo() throws IOException {
        Files.walkFileTree(Paths.get("src/main/resources"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件: " + file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("目录: " + dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }

    private static void walkDemo() {
        //        FileReadDemo();
        try (Stream<Path> paths = Files.walk(Paths.get("src/main/resources"))) {
            paths
                .filter(Files::isRegularFile)
                .filter(p -> p.toString().endsWith(".txt"))
                .forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void fileReadDemo() throws IOException {
        Path basePath = Paths.get("src/main/resources/txt");
        Path txtPath = basePath.resolve("output.txt");
        byte[] bytes = Files.readAllBytes(txtPath);
        String s = Files.readString(txtPath);
        System.out.println(s);
    }

    private static void pathDemo() {
        Path basePath = Paths.get("src", "main", "resource");
        Path txtPath = basePath.resolve("txt");

        System.out.println("拼接路径: " + txtPath.resolve("hello.txt"));
        System.out.println("兄弟路径: " + txtPath.resolveSibling("data/hello.bin"));
        System.out.println("父路径: " + txtPath.getParent());
        System.out.println("文件名: " + txtPath.getFileName());
        System.out.println("路径规范化: " + Paths.get("a/b/../c").normalize());
        System.out.println("是否以 src 开头: " + txtPath.startsWith("src"));
    }

    private static void objectDeserialize() {
        Employee newEmp = new Employee();
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/main/resources/data/employee.dat"))) {
            newEmp = (Employee) ois.readObject();
            System.out.println("读取到的员工对象：");
            System.out.println(newEmp);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/main/resources/data/employee.dat"))) {
            Employee newEmp2 = (Employee) ois.readObject();
            System.out.println(newEmp == newEmp2);  //false
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void objectSerialize() {
        Employee emp = new Employee(101, "Alice", 28, 8500.5);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/main/resources/data/employee.dat"))) {
            oos.writeObject(emp);
            System.out.println("员工对象已序列化并写入文件。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void outputStreamDemo() {
        String filePath = "src/main/resources/txt/output.bin";
        try (var writer = new BufferedWriter(new FileWriter("src/main/resources/txt/output.txt"))) {
            writer.write("Hello, world!");
            writer.flush(); // 将内容从缓冲区写入文件
        } catch (IOException e) {
            e.printStackTrace();
        }


        try (var dos = new DataOutputStream(new FileOutputStream(filePath))) {
            dos.writeInt(32768);
            dos.writeDouble(3.14);
            dos.writeBoolean(true);
            dos.writeUTF("Hello");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try (DataInputStream dis = new DataInputStream(new FileInputStream(filePath))) {
//            var i = dis.readInt();
            var i1 = dis.readShort();
            var i2 = dis.readShort();
            var d = dis.readDouble();
            boolean b = dis.readBoolean();
            String s = dis.readUTF();
//            System.out.println(""+i+d+b+s);
            System.out.println("" + i1 + i2 + d + b + s);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private static void charsetDemo() {
        System.out.println(256 * 98 + 17);
        String s = new String("我1a😀");
        char[] charArray = s.toCharArray();
        byte[] bytes = s.getBytes(StandardCharsets.UTF_16);

        IntStream.range(0, bytes.length)
            .map(i -> bytes[i])
            .forEach(System.out::println);

        System.out.println("==============");
        IntStream.range(0, charArray.length)
            .map(i -> charArray[i])
            .forEach(System.out::println);
    }


    private static void closeMethod() {
        AutoCloseable resource = () -> {
            throw new Exception("AnyType");
        };

        Closeable closeable = () -> {
            throw new IOException("Only IOException Type");
            // throw new ArithmeticException();
        };

        try {
            resource.close();
        } catch (Exception e) {
            System.out.println("Caught from resource: " + e);
        }

        try {
            closeable.close();
        } catch (IOException e) {
            System.out.println("Caught from closeable: " + e);
        }
    }

}
